package com.beta.cms.common.until;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

/**
 * @Description Lucene工具类
 * @Date 2017年5月3日 上午10:02:18
 * @author xie
 * @version 1.0.0
 */
public class LuceneUtils {

	/**
	 * 最多查询出多少数据
	 */
	private static final int SEARCH_MAX_COUNT = 1000;

	/**
	 * 分词索引路径
	 */
	private static final String PATH_INDEX = Configuration.getInstance().getString("path_index");

	/**
	 * @Description 创建分词索引，每个map是一个完整的文章
	 * @param map
	 * @param path
	 */
	public static void createIndex(List<Map<String, Object>> mapList) {
		try {
			// 创建分词器
			Analyzer analyzer = new SmartChineseAnalyzer();
			// 创建IndexWriterConfig
			IndexWriterConfig iwc = new IndexWriterConfig(analyzer);
			// 创建writer
			IndexWriter iw = new IndexWriter(getDirectory(), iwc);
			// 创建文档
			Document doc = null;
			for (Map<String, Object> map : mapList) {
				// 添加索引前先删除原来的索引
				Term term = new Term("id", map.get("id").toString());
				Query query = new TermQuery(term);
				iw.deleteDocuments(query);
				doc = new Document();
				// 遍历map,添加每一个文章信息
				Set<String> keys = map.keySet();
				Iterator<String> keysIterator = keys.iterator();
				while (keysIterator.hasNext()) {
					String key = keysIterator.next();
					if ("id".equals(key)) {
						doc.add(new StringField("id", map.get("id").toString(), Field.Store.YES));
						continue;
					}
					doc.add(new TextField(key, map.get(key).toString(), Field.Store.YES));
				}
				iw.addDocument(doc);
			}
			iw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * @Description 搜索工具类
	 * @param queryField
	 * @param queryCondition
	 * @param resultField
	 * @return
	 */
	public static List<Map<String, Object>> queryIndex(String queryField, String queryCondition,
			List<String> resultFieldList) {
		List<Map<String, Object>> mapList = null;
		try {
			mapList = new ArrayList<Map<String, Object>>();
			// 创建分词器
			Analyzer analyzer = new SmartChineseAnalyzer();
			// 创建reader
			IndexReader ir = DirectoryReader.open(getDirectory());
			// 搜索器
			IndexSearcher searcher = new IndexSearcher(ir);
			// 查询哪个字段
			QueryParser parse = new QueryParser(queryField, analyzer);
			// 查询关键字
			Query query = parse.parse(queryCondition);
			TopDocs topDocs = searcher.search(query, SEARCH_MAX_COUNT);
			// 碰撞结果
			ScoreDoc[] hits = topDocs.scoreDocs;
			for (int i = 0; i < hits.length; i++) {
				Map<String, Object> map = new HashMap<String, Object>();
				ScoreDoc hit = hits[i];
				Document hitDoc = searcher.doc(hit.doc);
				// 结果按照得分来排序。主要由 关键字的个数和权值来决定
				map.put("hit.doc", hit.doc);
				map.put("hit.score", hit.score);
				for (String resultField : resultFieldList) {
					if (hitDoc.get(resultField) != null) {
						map.put(resultField, hitDoc.get(resultField));
					}
				}
				mapList.add(map);
			}
			ir.close();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return mapList;
	}

	/**
	 * @Description 根据ID集合删除索引
	 * @param list
	 */
	public static void deleteIndex(List<String> list) {
		try {
			Analyzer analyzer = new SmartChineseAnalyzer();
			IndexWriterConfig conf = new IndexWriterConfig(analyzer);
			IndexWriter iw = new IndexWriter(getDirectory(), conf);
			if (list != null && list.size() > 0) {
				Term[] terms = new Term[list.size()];
				for (int i = 0; i < list.size(); i++) {
					Term term = new Term("id", list.get(i));
					terms[i] = term;
				}
				iw.deleteDocuments(terms);
			}
			// 也可以传一个Query数组对象，将Query查找的结果删除。
			// QueryParser parse = new QueryParser("id", analyzer);
			// 查询关键字
			// Query query = parse.parse("1");
			// iw.deleteDocuments(query);
			iw.commit();
			iw.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 删除并创建新的索引目录
	 */
	public static void removeAllIndex() {
		File file = new File(PATH_INDEX);
		if (file.isDirectory()) {
			deleteDir(file);
		}
		file.mkdir();
	}

	/**
	 * @Description 获取目录
	 * @return
	 */
	private static Directory getDirectory() {
		// 创建索引目录
		Directory directory = null;
		try {
			directory = FSDirectory.open(Paths.get(PATH_INDEX));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return directory;
	}

	/**
	 * @Description 递归删除目录下的所有文件及子目录下所有文件
	 * @param dir
	 * @return
	 */
	private static boolean deleteDir(File dir) {
		if (dir.isDirectory()) {
			String[] children = dir.list();
			for (int i = 0; i < children.length; i++) {
				boolean success = deleteDir(new File(dir, children[i]));
				if (!success) {
					return false;
				}
			}
		}
		// 目录此时为空，可以删除
		return dir.delete();
	}

	public static void main(String[] args) {
		// List<Map<String, Object>> s1 = new ArrayList<Map<String, Object>>();
		// Map<String, Object> m1 = new HashMap<String, Object>();
		// m1.put("id", 1);
		// m1.put("content",
		// "习近平指出，今年是伟大的国际主义战士、中国人民的老朋友、工合运动重要发起人、培黎学校创始人路易·艾黎诞辰120周年。艾黎与中国人民风雨同舟，在华工作生活60年，为中国人民和新西兰人民架起了友谊之桥。他和宋庆龄、斯诺等发起成立的工合国际，为支援中国革命和社会主义建设作出了重要贡献");
		// s1.add(m1);
		//
		// Map<String, Object> m2 = new HashMap<String, Object>();
		// m2.put("id", 9);
		// m2.put("content",
		// "国人民对外友好协会21日在北京人民大会堂举办座谈会，纪念路易·艾黎诞辰120周年。中共中央政治局委员、国家副主席李源潮出席座谈会并讲话。他指出，习近平总书记在回信中充分肯定了艾黎为中国民族独立、国家建设事业作出的重要贡献。当前，中国人民正在以习近平同志为核心的党中央领导下，为实现“两个一百年”目标和中华民族伟大复兴的中国梦而奋斗。中国高举和平、发展、合作、共赢的旗帜，愿与包括新西兰在内的世界各国人民一道，为构建人类命运共同体、促进人类和平与发展的崇高事业共同努力。今天我们发扬艾黎精神，就是要继承他伟大的国际主义精神，谱写人民国际友谊新篇章");
		// s1.add(m2);
		// LuceneUtils.createIndex(s1);

		List<String> s = new ArrayList<String>();
		s.add("id");
		s.add("content");
		List<Map<String, Object>> str = LuceneUtils.queryIndex("content", "中共中央政治局委员", s);
		for (Map<String, Object> map : str) {
			for (Map.Entry<String, Object> entry : map.entrySet()) {
				System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
			}
		}
		System.out.println("总条数= " + str.size());

		// LuceneUtils.removeAllIndex();

		// List<String> ids = new ArrayList<String>();
		// ids.add("9");
		// LuceneUtils.deleteIndex(ids);
	}
}
